package com.xcdh.trading.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xcdh.commons.query.QueryPayload;
import com.xcdh.commons.utils.RestTemplateUtil;
import com.xcdh.commons.utils.StringUtil;
import com.xcdh.trading.entity.*;
import com.xcdh.trading.mapper.DayTransactionDataMapper;
import com.xcdh.trading.query.StockPayload;
import com.xcdh.trading.response.TradingRes;
import com.xcdh.trading.service.*;
import com.xcdh.trading.util.TuShareApi;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class DayTransactionDataServiceImpl extends ServiceImpl<DayTransactionDataMapper, DayTransactionData> implements DayTransactionDataService {
    @Autowired
    private AStockService aStockService ;
    @Autowired
    private TempStocksService tempStocksService ;
    @Autowired
    private DayTransactionDataMapper dayTransactionDataMapper ;
    @Autowired
    private StockInfoService stockInfoService ;
    @Autowired
    public HotMoneyTrcService hotMoneyTrcService ;
    @Autowired
    public CapitalFlowService capitalFlowService ;
    @Autowired
    public StockBiddingService stockBiddingService ;
    @Autowired
    private DailyIndicatorsService dailyIndicatorsService ;



    @Override
    public void syncTransactionData(String dataCode) {
        TradingRes tradingRes = TuShareApi.post("daily", dataCode);
        // 每日交易数据
        List<DayTransactionData> list = tradingRes.parse(DayTransactionData.class);
        List<DayTransactionData> transactionDataList = lambdaQuery().eq(DayTransactionData::getTradeDateCode, dataCode).list();
        Map<String, DayTransactionData> dataMap = transactionDataList.stream().collect(Collectors.toMap(DayTransactionData::getTsCode, item -> item));

        List<AStock> aStockList = aStockService.lambdaQuery().list();
        Map<String, AStock> stockMap = aStockList.stream().collect(Collectors.toMap(AStock::getTsCode, item -> item));

        List<DayTransactionData> summaryTrDataList = dayTransactionDataMapper.summaryTrData(dataCode);

        //
        Map<String, DayTransactionData> transactionDataMap = summaryTrDataList.stream()
                .collect(Collectors.toMap(DayTransactionData::getTsCode, Function.identity()));

        //游资交易
        List<HotMoneyTrc> hotMoneyTrcList = hotMoneyTrcService.statisticsBuyMoneyByTradeDate(dataCode);
        Map<String, HotMoneyTrc> hotMoneyTrcMap = hotMoneyTrcList.stream()
                .collect(Collectors.toMap(HotMoneyTrc::getTsCode, Function.identity()));

        // 每日指标
        Map<String, DailyIndicators> dailyIndicatorsMap = dailyIndicatorsService
                .lambdaQuery()
                .eq(DailyIndicators::getTradeDate, dataCode).list().stream()
                .collect(Collectors.toMap(DailyIndicators::getTsCode, Function.identity()));

        // 资金流向
        List<CapitalFlow> capitalFlows = capitalFlowService.statisticsBuyMoney(dataCode);
        Map<String, CapitalFlow> capitalFlowMap = capitalFlows.stream()
                .collect(Collectors.toMap(CapitalFlow::getTsCode, Function.identity()));

        for (DayTransactionData dayTransactionData : list) {
            String tsCode = dayTransactionData.getTsCode();
            DayTransactionData transactionData = dataMap.get(tsCode);
            dayTransactionData.setVolumeRatio(0f) ;
            dayTransactionData.setTurnoverRate(0f);
            dayTransactionData.setHotAmount(0F);
            dayTransactionData.setBigAmount(0F);
            dayTransactionData.setSmallAmount(0F);
            dayTransactionData.setZdfNum(0);

            if(dailyIndicatorsMap.get(tsCode) != null){
                dayTransactionData.setVolumeRatio(dailyIndicatorsMap.get(tsCode).getVolumeRatio());
                dayTransactionData.setTurnoverRate(dailyIndicatorsMap.get(tsCode).getTurnoverRate());
            }
            if(capitalFlowMap.get(tsCode) != null){
                dayTransactionData.setBigAmount(capitalFlowMap.get(tsCode).getBigAmount());
                dayTransactionData.setSmallAmount(capitalFlowMap.get(tsCode).getSmallAmount());
            }
            if(hotMoneyTrcMap.get(tsCode) != null){
                dayTransactionData.setHotAmount(hotMoneyTrcMap.get(tsCode).getNetAmount());
            }
            DayTransactionData sunTrData = transactionDataMap.get(tsCode);
            if(sunTrData != null){
                dayTransactionData.setPctChgSum(sunTrData.getPctChgSum());
                dayTransactionData.setUpNum(sunTrData.getUpNum());
                dayTransactionData.setDownNum(sunTrData.getDownNum());
                dayTransactionData.setZfNumSum(sunTrData.getZfNumSum());
                dayTransactionData.setDfNumSum(sunTrData.getDfNumSum());
                dayTransactionData.setZdRatio(div(sunTrData.getUpNum() , sunTrData.getDownNum()));
                dayTransactionData.setZdfRatio(div(sunTrData.getZfNumSum() , sunTrData.getDfNumSum()));
                dayTransactionData.setZdfNum(sub(sunTrData.getZfNumSum() , sunTrData.getDfNumSum()));
            }

            if(transactionData == null){
                try{
                    AStock aStock = stockMap.get(dayTransactionData.getTsCode());
                    dayTransactionData.setTradeDateCode(dataCode);
                    dayTransactionData.setTradeDate(DateUtil.formatDate(DateUtil.parse(dataCode)));
                    dayTransactionData.setName(aStock.getName());
                    save(dayTransactionData) ;
                }catch (Exception e){
                    e.printStackTrace();
                }
            }else{
                dayTransactionData.setId(transactionData.getId());
                updateById(dayTransactionData) ;
            }
        }
    }

    @Override
    public void countTransactionData(String dataCode) {
        Map<String, StockTradeInfo> infoMap = getZtb(dataCode);
        List<DailyIndicators> biddingList = dailyIndicatorsService.lambdaQuery()
                .eq(DailyIndicators::getTradeDate, dataCode).list();
        // 每日指标
        Map<String, DailyIndicators> dailyIndicatorsMap = biddingList.stream()
                .collect(Collectors.toMap(DailyIndicators::getTsCode, Function.identity()));
        // 历史交易汇总
        List<DayTransactionData> summaryTrData = dayTransactionDataMapper.summaryTrData(dataCode);
        Map<String, DayTransactionData> trDataMap = summaryTrData.stream()
                .collect(Collectors.toMap(DayTransactionData::getTsCode, Function.identity()));

        //当日数据
        List<DayTransactionData> dataList = lambdaQuery()
                .eq(DayTransactionData::getTradeDate, dataCode)
                .list();
        // 资金流向
        List<CapitalFlow> capitalFlows = capitalFlowService.statisticsBuyMoney(dataCode);
        Map<String, CapitalFlow> capitalFlowMap = capitalFlows.stream()
                .collect(Collectors.toMap(CapitalFlow::getTsCode, Function.identity()));

        List<HotMoneyTrc> hotMoneyTrcList = hotMoneyTrcService.statisticsBuyMoneyByTradeDate(dataCode);
        Map<String, HotMoneyTrc> hotMoneyTrcMap = hotMoneyTrcList.stream()
                .collect(Collectors.toMap(HotMoneyTrc::getTsCode, Function.identity()));

        for (DayTransactionData trData :dataList ) {
            String tsCode = trData.getTsCode();
            DayTransactionData sumData = trDataMap.get(tsCode) ;
            StockInfo stockInfo = new StockInfo() ;
            stockInfo.setPrice(BigDecimal.valueOf(trData.getClose()));
            stockInfo.setName(trData.getName());
            stockInfo.setDownNum(sumData.getDownNum());
            stockInfo.setUpNum(sumData.getUpNum());
            stockInfo.setTradeDate(trData.getTradeDate());
            stockInfo.setTsCode(tsCode);
            stockInfo.setPctChgSum(sumData.getPctChgSum());
            StockTradeInfo tradeInfo = infoMap.get(tsCode);
            stockInfo.setLimit("");
            int uNum = 0 ,dNum =  0 ;
            if(tradeInfo != null){
                uNum = "U".equals(tradeInfo.getLimit()) ? tradeInfo.getLimitTimes() : 0;
                dNum = "D".equals(tradeInfo.getLimit()) ? tradeInfo.getLimitTimes() : 0;
            }
            stockInfo.setNums(uNum) ;
            stockInfo.setDNums(dNum) ;
            stockInfo.setVolumeRatio(0f) ;
            stockInfo.setTurnoverRate(0f);
            stockInfo.setHotAmount(0F);
            stockInfo.setBigAmount(0F);
            stockInfo.setSmallAmount(0F);
            stockInfo.setZdfRatio(div(sumData.getZfNumSum() , sumData.getDfNumSum()));
            stockInfo.setZdRatio(div(sumData.getUpNum() , sumData.getDownNum()));
            stockInfo.setZdfNum(sub(sumData.getZfNumSum() , sumData.getDfNumSum()));
            stockInfo.setZfNum(sumData.getZfNumSum());
            stockInfo.setDfNum(sumData.getDfNumSum());
            if(infoMap.get(tsCode) != null){
                BeanUtils.copyProperties(infoMap.get(tsCode) , stockInfo);
                stockInfo.setOpenNum(infoMap.get(tsCode).getOpenTimes());
            }
            stockInfo.setPctChg(BigDecimal.valueOf(trData.getPctChg()));
            if(dailyIndicatorsMap.get(tsCode) != null){
                stockInfo.setVolumeRatio(dailyIndicatorsMap.get(tsCode).getVolumeRatio());
                stockInfo.setTurnoverRate(dailyIndicatorsMap.get(tsCode).getTurnoverRate());
            }
            if(capitalFlowMap.get(tsCode) != null){
                stockInfo.setBigAmount(capitalFlowMap.get(tsCode).getBigAmount());
                stockInfo.setSmallAmount(capitalFlowMap.get(tsCode).getSmallAmount());
            }
            if(hotMoneyTrcMap.get(tsCode) != null){
                stockInfo.setHotAmount(hotMoneyTrcMap.get(tsCode).getNetAmount());
            }
            stockInfoService.saveOrUpdate(stockInfo);
        }
    }

    public Integer div(int a , int b){
        if(b == 0){
            return a ;
        }
        return a/b ;
    }

    public Integer sub(int a , int b){
        return a-b ;
    }

    public Map<String,StockTradeInfo> getZtb(String dataCode){
        TradingRes limitStep = TuShareApi.post("limit_list_d", dataCode);
        return zTbToMap(limitStep.parse(StockTradeInfo.class)) ;
    }

    public Map<String,StockTradeInfo> zTbToMap(List<StockTradeInfo> list){
        Map<String,StockTradeInfo> result = new HashMap<>() ;
        for (StockTradeInfo stockInfo : list) {
            result.put(stockInfo.getTsCode() , stockInfo) ;
        }
        return result ;
    }

    @Override
    public List<DayTransactionData> summaryTrData(String dataCode) {
        return dayTransactionDataMapper.summaryTrData(dataCode);
    }

    @Override
    public IPage<DayTransactionData> listByPage(Page<DayTransactionData> pageDto, QueryWrapper<DayTransactionData> queryWrapper) {
        return dayTransactionDataMapper.listByPage(pageDto , queryWrapper);
    }

    @Override
    public IPage<DayTransactionData> xGuList(Page<DayTransactionData> pageDto, QueryWrapper<DayTransactionData> queryWrapper) {
        List<String> tradeDateTop3 = stockInfoService.selectMaxTradeDateTop3();
        String tradeDate = stockInfoService.selectMaxTradeDate();
        queryWrapper.in("trade_date"  ,tradeDateTop3).gt("pct_chg" , -1) ;
        queryWrapper.groupBy("ts_code")
                .having("sum(pct_chg) >= 6 AND count(1) >= 3 ")
                .orderByDesc("sum(pct_chg)" ) ;
        IPage<DayTransactionData> xGuList = dayTransactionDataMapper.xGuList(pageDto, queryWrapper);
        List<String> list = xGuList.getRecords()
                .stream().map(DayTransactionData::getTsCode)
                .collect(Collectors.toList());
        if(!list.isEmpty()){
            List<DayTransactionData> dataList = lambdaQuery().eq(DayTransactionData::getTradeDate, tradeDate).in(DayTransactionData::getTsCode, list).list();
            Map<String, DayTransactionData> dataMap = dataList.stream().collect(Collectors.toMap(DayTransactionData::getTsCode, item -> item));
            for (DayTransactionData record : xGuList.getRecords()) {
                String tsCode = record.getTsCode();
                DayTransactionData transactionData = dataMap.get(tsCode);
                record.setClose(transactionData != null ?transactionData.getClose() : 0f);
            }
        }
        return xGuList;
    }


}
